﻿using Abp.Domain.Repositories;
using BRMC.IntelligentCommunity.IntelligentCommunity.Parkings;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BRMC.IntelligentCommunity.Parkings.CarLog
{
    public class CarLogHistoryAppService: IntelligentCommunityAppServiceBase, ICarLogHistoryAppService
    {

        private readonly IRepository<CarLogHistory, long> _carLogHistoryRepository;
        private readonly IRepository<CarlogRealTime, long> _carLogRealTimeRepository;
        private readonly IRepository<Place, long> _placeRepository;
        private readonly IRepository<UserParkinginfo, long> _userParkingInfoRepository;
        private readonly IRepository<CarInfo, long> _carInfoRepository;
        private readonly IRepository<Paymethod, long> _paymethodRepository;
        private readonly IParkingsBillingSchemeAppService _parkingsBillingSchemepService;

        public CarLogHistoryAppService(
            IRepository<CarLogHistory, long> carLogHistoryRepository,
            IRepository<CarlogRealTime, long> carLogRealTimeRepository,
            IRepository<Place, long> placeRepository,
            IRepository<UserParkinginfo, long> userParkingInfoRepository,
            IRepository<CarInfo, long> carInfoRepository,
            IRepository<Paymethod, long> paymethodRepository,
            IParkingsBillingSchemeAppService parkingsBillingSchemepService
            )
        {
            _carLogHistoryRepository = carLogHistoryRepository;
            _carLogRealTimeRepository = carLogRealTimeRepository;
            _placeRepository= placeRepository;
            _userParkingInfoRepository = userParkingInfoRepository;
            _carInfoRepository = carInfoRepository;
            _paymethodRepository = paymethodRepository;
            _parkingsBillingSchemepService = parkingsBillingSchemepService;
        }

        /// <summary>
        /// 车辆入场
        /// </summary>
        /// <param name="carId">车辆Id</param>
        /// <param name="carNum">车牌号</param>
        /// <param name="parkingId">车场Id</param>
        /// <param name="inTime">入场时间</param>
        /// <param name="cam_id">设备Id</param>
        /// <param name="cam_ip">设备Ip</param>
        /// <param name="device">岗亭信息</param>
        /// <returns></returns>
        public async Task CarIn(long carId,string carNum, long parkingId, DateTime inTime,string cam_id,string cam_ip, Device device)
        {
            //车辆入场记录事件：
            //1.删除该车在场记录，修改在场记录对应使用车位状态，
            //2.判断是临时车或月租车（0：临时车，1：月租车）,
            //3.新增在场记录
            //4.月租车记录停放车位

            #region 1.删除所有当前车辆在场记录，修改未出场的日志状态，改为已出场,如果有车位停放信息，修改车位状态为未停
            await _carLogRealTimeRepository.DeleteAsync(e => e.CarNum == carNum && e.ParkingId == parkingId);

            var carLogHistoryList = await _carLogHistoryRepository.GetAll().Where(e => e.CarNum == carNum && e.ParkingId == parkingId && e.IsOut == false).ToListAsync();
            foreach (var carLogHistory in carLogHistoryList)
            {
                carLogHistory.IsOut = true;
                await _carLogHistoryRepository.UpdateAsync(carLogHistory);
            }

            var placeListByCarLog = await _placeRepository.GetAll()
                .Where(e => carLogHistoryList.Where(c => c.PlaceId.HasValue).Select(c => c.PlaceId).Contains(e.Id))
                .ToListAsync();
            foreach (var placeCarLog in placeListByCarLog)
            {
                placeCarLog.PlaceSatus = 0;
                await _placeRepository.UpdateAsync(placeCarLog); 
            }

            #endregion

            #region 2.判断临时车或月租车 0:临时车，1月租车,月租车可停车位

            var placeList = await _userParkingInfoRepository.GetAll().Where(e => e.CarId == carId && e.ParkingId == parkingId)
                .Select(e => new { Id = e.PlaceId, EndTime = e.EndTime })
                .Join(_placeRepository.GetAll(), 
                        l => new { l.Id, l.EndTime},
                        r =>new { r.Id, r.EndTime}, 
                        (l,r) => r)
                .ToListAsync();                
            var carIdQuery = _userParkingInfoRepository.GetAll().Where(e => placeList.Any(p=>p.Id ==e.PlaceId && p.EndTime == e.EndTime)).Select(e => e.CarId);
            var carNumList = _carInfoRepository.GetAll().Where(e => carIdQuery.Contains(e.Id)).Select(e => e.CarNum);
            var carLogCount = await _carLogHistoryRepository.GetAll().CountAsync(e=>e.ParkingId == parkingId && e.IsOut == false && carNumList.Contains(e.CarNum));
            var carType = (carLogCount >= placeList.Count ? 0 : 1);
            var place = placeList.FirstOrDefault(e => e.PlaceSatus == 0);
            var placeId = place?.Id;

            #endregion

            #region 3.新增在场记录

            var newCarLogRealTime = new CarlogRealTime()
            {
                ParkingId = parkingId,
                GuardId = device.GuardId,
                CarNum = carNum,
                PlaceId = placeId,
                CarType = carType,
                PayStatus = 1,
                LogTime = inTime,
                TenantId = device.TenantId,
                Neighbourhood_id = device.Neighbourhood_id
            };
            await _carLogRealTimeRepository.InsertAsync(newCarLogRealTime);
            var newCarLogHistory = new CarLogHistory()
            {
                LogType = 1,
                ParkingId = parkingId,
                CamId = cam_id,
                GuardId = device.GuardId,
                Ipaddr = cam_ip,
                CarType = carType,
                LogTime = inTime,
                TenantId = device.TenantId,
                CarNum = carNum,
                Neighbourhood_id = device.Neighbourhood_id,
                CarLogRealTimeId = newCarLogRealTime.Id,
                IsOut = false,
                PlaceId = placeId,
                CarId = carId
            };
            await _carLogHistoryRepository.InsertAsync(newCarLogHistory);

            #endregion

            #region 4.月租车记录占用车位
            if (place != null)
            {
                place.PlaceSatus = 1;
                await _placeRepository.UpdateAsync(place);
            }

            #endregion
        }

        /// <summary>
        /// 车辆出场
        /// </summary>
        /// <param name="carId">车辆Id</param>
        /// <param name="carNum">车牌号</param>
        /// <param name="parkingId">车场Id</param>
        /// <param name="outTime">出场时间</param>
        /// <param name="cam_id">设备Id</param>
        /// <param name="cam_ip">设备Ip</param>
        /// <param name="device">岗亭信息</param>
        /// <returns></returns>
        public async Task<CostAndRemark> CarOut(long carId, string carNum, long parkingId, DateTime outTime, string cam_id, string cam_ip, Device device)
        {
            var costAndRemark = new CostAndRemark() { Cost = 0, Remark ="" };
            //车辆出场记录事件：
            //1.获取车辆入场记录，没有入场或标记已出场，直接返回费用0；
            //2.计算应交费用
            //3.费用为0时删除在场记录，修改入场日志，应交费用不为0时，不修改入场记录，不删除在场记录
            //4.返回费用及备注

            //1
            var carLogLast = await _carLogHistoryRepository.GetAll().Where(e => e.ParkingId == parkingId && e.CarNum == carNum).OrderByDescending(e=>e.LogTime).FirstOrDefaultAsync();
            if (carLogLast == null) return costAndRemark;
            if (carLogLast.IsOut == true) return costAndRemark;

            //2
            costAndRemark = await _parkingsBillingSchemepService.GetCost(outTime, carLogLast);

            //3
            if (costAndRemark.Cost == 0)
            {
                if (carLogLast.CarLogRealTimeId.HasValue)
                {
                    await _carLogRealTimeRepository.DeleteAsync(carLogLast.CarLogRealTimeId.Value);
                }

                carLogLast.IsOut = true;
                carLogLast.OutCamId = cam_id;
                carLogLast.OutGuardId = device.Id;
                carLogLast.OutIpaddr = cam_ip;
                
                await _carLogHistoryRepository.UpdateAsync(carLogLast);
            }

            //4
            return costAndRemark;
        }
    }
}
